#!/usr/bin/env python
# Create: 2018/12/7
__author__ = '749B'

import getpass
import logging
import os
import paramiko

from utils.base64p import b64decode_str

logger = logging.getLogger(__name__)


class SSHClient(object):

    def __init__(self, host, port=22, username='root', password=None, filename=r'var/log/messages'):
        self.host = host
        self.port = port
        self.username = username
        self.password = b64decode_str(password) if password else getpass.getpass("输入密码: ")
        self.filename = filename + '-*'

        self.alias = None
        self.ssh = None
        self.sftp = None
        self.hostname = None  # hostname是用于连接的主机名，这个是ssh通过hostname获取到的主机名

    def main(self):
        """重构这个方法，作为业务的入口"""
        pass

    def get_ssh(self):
        if self.ssh is None:
            self.ssh = paramiko.SSHClient()
            self.ssh.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
            self.ssh.connect(hostname=self.host, port=self.port, username=self.username, password=self.password)

    def open_sftp(self):
        if self.sftp is None:
            self.sftp = self.ssh.open_sftp()

    def exec_command(self, cmd, res_report=True, err_report=True):
        stdin, stdout, stderr = self.ssh.exec_command(cmd)
        res, err = stdout.read(), stderr.read()
        if res_report and res:
            msg = "SSH 执行命令: %s 返回: \n%s" % (cmd, res.decode())
            logger.debug(msg)
        if err_report and err:
            msg = 'SSH 执行命令: %s 有错误: %s' % (cmd, err.decode())
            logger.debug(msg)
        return res, err

    def sftp_files(self, res, node=None):
        file_list = res.decode().split()
        self.open_sftp()
        for file in file_list:
            self.sftp_get_file(file, node)
        self.sftp.close()

    def sftp_get_file(self, file, node=None):
        # 拼接上本地的目录
        base_folder = os.path.split(__file__)[0]
        # 可以指定名字，如果不指定，就去获取hostname
        hostname = node or self.cmd_hostname()
        local_file = os.path.join(base_folder, 'download', hostname, os.path.split(file)[1])
        # 如果文件存在就不下载
        if os.path.exists(local_file) or os.path.exists(local_file + '_db'):
            print("文件已经存在，不下载", file)
            return
        # 检查文件夹，如果是存在就创建
        folder, filename = os.path.split(local_file)
        if not os.path.exists(folder):
            print("创建文件夹:", folder)
            os.makedirs(folder)

        # 下载文件
        print("下载文件到:", local_file)
        self.sftp.get(file, local_file)

    def cmd_hostname(self):
        if self.hostname is not None:
            return self.hostname
        self.hostname = "Unknown"
        res, err = self.exec_command("hostname")
        if res:
            self.hostname = res.decode().strip()
        return self.hostname

    def path_exists(self, path, *arge, **kwargs):
        """执行命令，返回路径是否存在
        执行上传文件之前，检查目标文件是否存在
        """
        res, err = self.exec_command('ls %s' % path, *arge, **kwargs)
        result = (bool(res) << 1) + bool(err)
        if result == 0:  # 没有返回结果
            raise UserWarning("查找文件，没有返回结果")
        elif result == 1:  # 有错误返回，就是没有该文件，可以上传
            return False
        elif result == 2:  # 找到文件了，不能上传
            return True
        elif result == 3:  # 既有结果，也有错误
            raise UserWarning("查找文件,既有结果，也有错误")
        else:
            raise UserWarning("查找文件，进入了预料之外的分支")








